/**
 * listeners:
 * addExtraDsValues
 */
ria.buildItem = function(spec) {
    if(!spec) {
        spec = {};
    }
    if(!spec.extraTplValues) {
        spec.extraTplValues = {};
    }
    // declaration of possible listeners
    spec.listeners = {};
    spec.listeners['extraValues'] = [];
    spec.listeners['postDisplay'] = [];

    spec.extraCommands = {};

    var fillTpl = function(html) { // "private method"
            spec.element.html(html);
            if(spec.element.fillTemplate.rptInstance) {
                spec.element.fillTemplate.rptInstance = null; //clear element template cache.
            }
            return this;
    };
    var ret = {
        display : function(actualView) {

            if(actualView) {
                this.setActualView(actualView);
            }
            var ds = clone(spec.ds);
            ds._jsObjName = spec.jsObjName;
            if(spec.extraTplValues) {
                for(i in spec.extraTplValues) {
                    ds[i] = spec.extraTplValues[i];
                }
            }
            if(spec.listeners.extraValues) {
                for(i in spec.listeners.extraValues) {
                    spec.listeners.extraValues[i](ds);
                }
            }
            var actualTplName = spec.views[spec.actualView].tpl;
            var actualDecoratorName = spec.views[spec.actualView].decorator;
            if(actualDecoratorName) {
                if(spec.decorators == undefined || spec.decorators[actualDecoratorName] == undefined) {
                    throw "Decorator " + actualDecoratorName + " is not defined";
                }
                fillTpl(spec.tpls[actualTplName]);
                spec.element.fillTemplate(ds);
                ds._decorator_content = spec.element.html();
                spec.element.fillTemplate.rptInstance = null;
                fillTpl(spec.decorators[actualDecoratorName]);
                spec.element.fillTemplate(ds);
            }
            else {
                spec.element.fillTemplate.rptInstance = null;
                fillTpl(spec.tpls[actualTplName]);
                spec.element.fillTemplate(ds);
            }
            if(spec.listeners.postDisplay) {
                for(i in spec.listeners.postDisplay) {
                    spec.listeners.postDisplay[i].call(this,spec);
                }
            }
            return this;
        },
        setJsObjName : function(jsObjName) {spec.jsObjName = jsObjName; return this;},
        //callback
        bind : function (eventName, func) {
            if(!spec.listeners[eventName]) throw "Event " + eventName + " does not exists for this object.";
            spec.listeners[eventName][spec.listeners[eventName].length] = func;
            return this;
        },
        clearListeners : function (eventName) {
            if(!spec.listeners[eventName]) throw "Event " + eventName + " does not exists for this object.";
            spec.listeners[eventName] = [];
        },
        setExtraTplValue : function (name, value) {spec.extraTplValues[name] = value; return this;},
        setTpls : function(tpls) {spec.tpls = tpls; return this;},
        setDecorators : function(decorators) {spec.decorators = decorators; return this;},
        setViews : function(views) {spec.views = views; return this;},
        setActualView : function(actualView) {spec.actualView = actualView; return this;},
        setDs: function(ds) {spec.ds = ds;return this;},
        setListReference : function(list) {spec.list  = list; return this;},
        getElement: function() {return spec.element;},
        setElement: function(newElement) {spec.element = newElement;return this;},
        getDs: function() {return spec.ds;},
        setDsVal: function( name, value) {spec.ds[name] = value;return this;},
        hide : function() {this.getElement().hide();return this;},
        show : function() {this.getElement().show();return this;},
        clear : function() {this.getElement().html('')},
        getSpec : function() {return spec;},
        copy : function() {
          var item = ria.buildItem()
          .setTpls(clone(spec.tpls))
          .setDecorators(clone(spec.decorators))
          .setViews(clone(spec.views))
          .setActualView(clone(spec.actualView));
          for(eventName in spec.listeners) {
              var listeners = spec.listeners[eventName];
              for(i in listeners) {
                  item.bind(eventName,listeners[i]);
              }
          }
          return item
        },
        addCommand : function() {
            return function(name,func) {
                spec.extraCommands[name] = true;
                this[name] = function(params) {
                    func.call(this,spec,params);
                }
                return this;
            }
        }()
    }
    return ret;
};